/*----------------------------------------------------------------------*/
/* wl_Editor v 1.0 by revaxarts.com 
/* description: makes a WYSIWYG Editor
/* dependency: jWYSIWYG Editor
/*----------------------------------------------------------------------*/
define(["jquery"], function(jQuery){
    jQuery(document).ready(function($){
        /**
	 * WYSIWYG - jQuery plugin 0.97
 	 * (0.97.2 - From infinity)
	 *
	 * Copyright (c) 2008-2009 Juan M Martinez, 2010-2011 Akzhan Abdulin and all contributors
	 * https://github.com/akzhan/jwysiwyg
	 *
	 * Dual licensed under the MIT and GPL licenses:
	 *   http://www.opensource.org/licenses/mit-license.php
	 *   http://www.gnu.org/licenses/gpl.html
	 *
	 */
	
        /*jslint browser: true, forin: true */

        (function ($) {
            "use strict";
            /* Wysiwyg namespace: private properties and methods */
	
            var console = window.console ? window.console : {
                log: $.noop,
                error: function (msg) {
                    $.error(msg);
                }
            };
            var supportsProp = (('prop' in $.fn) && ('removeProp' in $.fn));
	
            function Wysiwyg() {
                this.controls = {
                    bold: {
                        groupIndex: 0,
                        visible: false,
                        tags: ["b", "strong"],
                        css: {
                            fontWeight: "bold"
                        },
                        tooltip: "Bold",
                        hotkey: {
                            "ctrl": 1, 
                            "key": 66
                        }
                    },
	
                    copy: {
                        groupIndex: 8,
                        visible: false,
                        tooltip: "Copy"
                    },
	
                    createLink: {
                        groupIndex: 6,
                        visible: false,
                        exec: function () {
                            var self = this;
                            if ($.wysiwyg.controls && $.wysiwyg.controls.link) {
                                $.wysiwyg.controls.link.init(this);
                            } else if ($.wysiwyg.autoload) {
                                $.wysiwyg.autoload.control("wysiwyg.link.js", function () {
                                    self.controls.createLink.exec.apply(self);
                                });
                            } else {
                                console.error("$.wysiwyg.controls.link not defined. You need to include wysiwyg.link.js file");
                            }
                        },
                        tags: ["a"],
                        tooltip: "Create link"
                    },
	
                    cut: {
                        groupIndex: 8,
                        visible: false,
                        tooltip: "Cut"
                    },
	
                    decreaseFontSize: {
                        groupIndex: 9,
                        visible: false,
                        tags: ["small"],
                        tooltip: "Decrease font size",
                        exec: function () {
                            this.decreaseFontSize();
                        }
                    },
	
                    h1: {
                        groupIndex: 7,
                        visible: false,
                        className: "h1",
                        command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
                        "arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h1>" : "h1",
                        tags: ["h1"],
                        tooltip: "Header 1"
                    },
	
                    h2: {
                        groupIndex: 7,
                        visible: false,
                        className: "h2",
                        command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
                        "arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h2>" : "h2",
                        tags: ["h2"],
                        tooltip: "Header 2"
                    },
	
                    h3: {
                        groupIndex: 7,
                        visible: false,
                        className: "h3",
                        command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
                        "arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h3>" : "h3",
                        tags: ["h3"],
                        tooltip: "Header 3"
                    },
                    h4: {
                        groupIndex: 7,
                        visible: false,
                        className: "h4",
                        command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
                        "arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h4>" : "h4",
                        tags: ["h4"],
                        tooltip: "Header 4"
                    },
	
                    h5: {
                        groupIndex: 7,
                        visible: false,
                        className: "h5",
                        command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
                        "arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h5>" : "h5",
                        tags: ["h5"],
                        tooltip: "Header 5"
                    },
	
                    h6: {
                        groupIndex: 7,
                        visible: false,
                        className: "h6",
                        command: ($.browser.msie || $.browser.safari || $.browser.opera) ? "FormatBlock" : "heading",
                        "arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<h6>" : "h6",
                        tags: ["h6"],
                        tooltip: "Header 6"
                    },
	
                    highlight: {
                        tooltip:     "Highlight",
                        className:   "highlight",
                        groupIndex:  1,
                        visible:     false,
                        css: {
                            backgroundColor: "rgb(255, 255, 102)"
                        },
                        exec: function () {
                            var command, node, selection, args;
	
                            if ($.browser.msie || $.browser.safari) {
                                command = "backcolor";
                            } else {
                                command = "hilitecolor";
                            }
	
                            if ($.browser.msie) {
                                node = this.getInternalRange().parentElement();
                            } else {
                                selection = this.getInternalSelection();
                                node = selection.extentNode || selection.focusNode;
	
                                while (node.style === undefined) {
                                    node = node.parentNode;
                                    if (node.tagName && node.tagName.toLowerCase() === "body") {
                                        return;
                                    }
                                }
                            }
	
                            if (node.style.backgroundColor === "rgb(255, 255, 102)" ||
                                node.style.backgroundColor === "#ffff66") {
                                args = "#ffffff";
                            } else {
                                args = "#ffff66";
                            }
	
                            this.editorDoc.execCommand(command, false, args);
                        }
                    },
	
                    html: {
                        groupIndex: 10,
                        visible: false,
                        exec: function () {
                            var elementHeight;
	
                            if (this.options.resizeOptions && $.fn.resizable) {
                                elementHeight = this.element.height();
                            }
	
                            if (this.viewHTML) {
                                this.setContent(this.original.value);
	
                                $(this.original).hide();
                                this.editor.show();
	
                                if (this.options.resizeOptions && $.fn.resizable) {
                                    // if element.height still the same after frame was shown
                                    if (elementHeight === this.element.height()) {
                                        this.element.height(elementHeight + this.editor.height());
                                    }
	
                                    this.element.resizable($.extend(true, {
                                        alsoResize: this.editor
                                    }, this.options.resizeOptions));
                                }
							
                                this.ui.toolbar.find("li").each(function () {
                                    var li = $(this);
	
                                    if (li.hasClass("html")) {
                                        li.removeClass("active");
                                    } else {
                                        li.removeClass('disabled');
                                    }
                                });
                            } else {
                                this.saveContent();
	
                                $(this.original).css({
                                    width:	this.element.outerWidth() - 6,
                                    height: this.element.height() - this.ui.toolbar.height() - 6,
                                    resize: "none"
                                }).show();
                                this.editor.hide();
							
                                if (this.options.resizeOptions && $.fn.resizable) {
                                    // if element.height still the same after frame was hidden
                                    if (elementHeight === this.element.height()) {
                                        this.element.height(this.ui.toolbar.height());
                                    }
	
                                    this.element.resizable("destroy");
                                }
	
                                this.ui.toolbar.find("li").each(function () {
                                    var li = $(this);
	
                                    if (li.hasClass("html")) {
                                        li.addClass("active");
                                    } else {
                                        if (false === li.hasClass("fullscreen")) {
                                            li.removeClass("active").addClass('disabled');
                                        }
                                    }
                                });
                            }
	
                            this.viewHTML = !(this.viewHTML);
                        },
                        tooltip: "View source code"
                    },
	
                    increaseFontSize: {
                        groupIndex: 9,
                        visible: false,
                        tags: ["big"],
                        tooltip: "Increase font size",
                        exec: function () {
                            this.increaseFontSize();
                        }
                    },
	
                    insertImage: {
                        groupIndex: 6,
                        visible: false,
                        exec: function () {
                            var self = this;
	
                            if ($.wysiwyg.controls && $.wysiwyg.controls.image) {
                                $.wysiwyg.controls.image.init(this);
                            } else if ($.wysiwyg.autoload) {
                                $.wysiwyg.autoload.control("wysiwyg.image.js", function () {
                                    self.controls.insertImage.exec.apply(self);
                                });
                            } else {
                                console.error("$.wysiwyg.controls.image not defined. You need to include wysiwyg.image.js file");
                            }
                        },
                        tags: ["img"],
                        tooltip: "Insert image"
                    },
	
                    insertOrderedList: {
                        groupIndex: 5,
                        visible: false,
                        tags: ["ol"],
                        tooltip: "Insert Ordered List"
                    },
	
                    insertTable: {
                        groupIndex: 6,
                        visible: false,
                        exec: function () {
                            var self = this;
	
                            if ($.wysiwyg.controls && $.wysiwyg.controls.table) {
                                $.wysiwyg.controls.table(this);
                            } else if ($.wysiwyg.autoload) {
                                $.wysiwyg.autoload.control("wysiwyg.table.js", function () {
                                    self.controls.insertTable.exec.apply(self);
                                });
                            } else {
                                console.error("$.wysiwyg.controls.table not defined. You need to include wysiwyg.table.js file");
                            }
                        },
                        tags: ["table"],
                        tooltip: "Insert table"
                    },
	
                    insertUnorderedList: {
                        groupIndex: 5,
                        visible: false,
                        tags: ["ul"],
                        tooltip: "Insert Unordered List"
                    },
	
                    italic: {
                        groupIndex: 0,
                        visible: false,
                        tags: ["i", "em"],
                        css: {
                            fontStyle: "italic"
                        },
                        tooltip: "Italic",
                        hotkey: {
                            "ctrl": 1, 
                            "key": 73
                        }
                    },
	
                    justifyLeft: {
                        visible: false,
                        groupIndex: 1,
                        css: {
                            textAlign: "left"
                        },
                        tooltip: "Justify Left"
                    },
	
                    justifyCenter: {
                        groupIndex: 1,
                        visible: false,
                        tags: ["center"],
                        css: {
                            textAlign: "center"
                        },
                        tooltip: "Justify Center"
                    },
	
                    justifyRight: {
                        groupIndex: 1,
                        visible: false,
                        css: {
                            textAlign: "right"
                        },
                        tooltip: "Justify Right"
                    },
	
                    justifyFull: {
                        groupIndex: 1,
                        visible: false,
                        css: {
                            textAlign: "justify"
                        },
                        tooltip: "Justify Full"
                    },
	
                    ltr: {
                        groupIndex: 9,
                        visible: false,
                        exec: function () {
                            var p = this.dom.getElement("p");
	
                            if (!p) {
                                return false;
                            }
	
                            $(p).attr("dir", "ltr");
                            return true;
                        },
                        tooltip : "Left to Right"
                    },
	
                    rtl: {
                        groupIndex: 9,
                        visible: false,
                        exec: function () {
                            var p = this.dom.getElement("p");
	
                            if (!p) {
                                return false;
                            }
	
                            $(p).attr("dir", "rtl");
                            return true;
                        },
                        tooltip : "Right to Left"
                    },
				
                    indent: {
                        groupIndex: 2,
                        visible: false,
                        tooltip: "Indent"
                    },
	
                    outdent: {
                        groupIndex: 2,
                        visible: false,
                        tooltip: "Outdent"
                    },
	
                    insertHorizontalRule: {
                        groupIndex: 5,
                        visible: false,
                        tags: ["hr"],
                        tooltip: "Insert Horizontal Rule"
                    },
	
                    paragraph: {
                        groupIndex: 7,
                        visible: false,
                        className: "paragraph",
                        command: "FormatBlock",
                        "arguments": ($.browser.msie || $.browser.safari || $.browser.opera) ? "<p>" : "p",
                        tags: ["p"],
                        tooltip: "Paragraph"
                    },
	
                    paste: {
                        groupIndex: 8,
                        visible: false,
                        tooltip: "Paste"
                    },
	
                    undo: {
                        groupIndex: 4,
                        visible: false,
                        tooltip: "Undo"
                    },
	
                    redo: {
                        groupIndex: 4,
                        visible: false,
                        tooltip: "Redo"
                    },
	
                    removeFormat: {
                        groupIndex: 10,
                        visible: false,
                        exec: function () {
                            this.removeFormat();
                        },
                        tooltip: "Remove formatting"
                    },
	
	
                    underline: {
                        groupIndex: 0,
                        visible: false,
                        tags: ["u"],
                        css: {
                            textDecoration: "underline"
                        },
                        tooltip: "Underline",
                        hotkey: {
                            "ctrl": 1, 
                            "key": 85
                        }
                    },
	
                    strikeThrough: {
                        groupIndex: 0,
                        visible: false,
                        tags: ["s", "strike"],
                        css: {
                            textDecoration: "line-through"
                        },
                        tooltip: "Strike-through"
                    },
	
                    subscript: {
                        groupIndex: 3,
                        visible: false,
                        tags: ["sub"],
                        tooltip: "Subscript"
                    },
	
                    superscript: {
                        groupIndex: 3,
                        visible: false,
                        tags: ["sup"],
                        tooltip: "Superscript"
                    },
	
                    code: {
                        visible : false,
                        groupIndex: 6,
                        tooltip: "Code snippet",
                        exec: function () {
                            var range	= this.getInternalRange(),
                            common	= $(range.commonAncestorContainer),
                            $nodeName = range.commonAncestorContainer.nodeName.toLowerCase();
                            if (common.parent("code").length) {
                                common.unwrap();
                            } else {
                                if ($nodeName !== "body") {
                                    common.wrap("<code/>");
                                }
                            }
                        }
                    },
				
                    cssWrap: {
                        visible : false,
                        groupIndex: 6,
                        tooltip: "CSS Wrapper",
                        exec: function () { 
                            $.wysiwyg.controls.cssWrap.init(this);
                        }
                    }
				
                };
	
                this.defaults = {
                    html: '<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>INITIAL_CONTENT</body></html>',
                    debug: false,
                    controls: {},
                    css: {},
                    events: {},
                    autoGrow: false,
                    autoSave: true,
                    brIE: true,					// http://code.google.com/p/jwysiwyg/issues/detail?id=15
                    formHeight: 270,
                    formWidth: 440,
                    iFrameClass: null,
                    initialContent: "<p>Initial content</p>",
                    maxHeight: 10000,			// see autoGrow
                    maxLength: 0,
                    messages: {
                        nonSelection: "Select the text you wish to link"
                    },
                    toolbarHtml: '<ul role="menu" class="toolbar"></ul>',
                    removeHeadings: false,
                    replaceDivWithP: false,
                    resizeOptions: false,
                    rmUnusedControls: false,	// https://github.com/akzhan/jwysiwyg/issues/52
                    rmUnwantedBr: true,			// http://code.google.com/p/jwysiwyg/issues/detail?id=11
                    tableFiller: "Lorem ipsum",
                    initialMinHeight: null,
	
                    controlImage: {
                        forceRelativeUrls: false
                    },
	
                    controlLink: {
                        forceRelativeUrls: false
                    },
	
                    plugins: { // placeholder for plugins settings
                        autoload: false,
                        i18n: false,
                        rmFormat: {
                            rmMsWordMarkup: false
                        }
                    }
                };
	
                this.availableControlProperties = [
                "arguments",
                "callback",
                "className",
                "command",
                "css",
                "custom",
                "exec",
                "groupIndex",
                "hotkey",
                "icon",
                "tags",
                "tooltip",
                "visible"
                ];
	
                this.editor			= null;
                this.editorDoc		= null;
                this.element		= null;
                this.options		= {};
                this.original		= null;
                this.savedRange		= null;
                this.timers			= [];
                this.validKeyCodes	= [8, 9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46];
	
                this.isDestroyed	= false;
	
                this.dom		= { // DOM related properties and methods
                    ie:		{
                        parent: null // link to dom
                    },
                    w3c:	{
                        parent: null // link to dom
                    }
                };
                this.dom.parent		= this;
                this.dom.ie.parent	= this.dom;
                this.dom.w3c.parent	= this.dom;
	
                this.ui			= {};	// UI related properties and methods
                this.ui.self	= this;
                this.ui.toolbar	= null;
                this.ui.initialHeight = null; // ui.grow
	
                this.dom.getAncestor = function (element, filterTagName) {
                    filterTagName = filterTagName.toLowerCase();
	
                    while (element && "body" !== element.tagName.toLowerCase()) {
                        if (filterTagName === element.tagName.toLowerCase()) {
                            return element;
                        }
	
                        element = element.parentNode;
                    }
	
                    return null;
                };
	
                this.dom.getElement = function (filterTagName) {
                    var dom = this;
	
                    if (window.getSelection) {
                        return dom.w3c.getElement(filterTagName);
                    } else {
                        return dom.ie.getElement(filterTagName);
                    }
                };
	
                this.dom.ie.getElement = function (filterTagName) {
                    var dom			= this.parent,
                    selection	= dom.parent.getInternalSelection(),
                    range		= selection.createRange(),
                    element;
	
                    if ("Control" === selection.type) {
                        // control selection
                        if (1 === range.length) {
                            element = range.item(0);
                        } else {
                            // multiple control selection
                            return null;
                        }
                    } else {
                        element = range.parentElement();
                    }
	
                    return dom.getAncestor(element, filterTagName);
                };
	
                this.dom.w3c.getElement = function (filterTagName) {
                    var dom		= this.parent,
                    range	= dom.parent.getInternalRange(),
                    element;
	
                    if (!range) {
                        return null;
                    }
	
                    element	= range.commonAncestorContainer;
	
                    if (3 === element.nodeType) {
                        element = element.parentNode;
                    }
	
                    // if startContainer not Text, Comment, or CDATASection element then
                    // startOffset is the number of child nodes between the start of the
                    // startContainer and the boundary point of the Range
                    if (element === range.startContainer) {
                        element = element.childNodes[range.startOffset];
                    }
	
                    return dom.getAncestor(element, filterTagName);
                };
	
                this.ui.addHoverClass = function () {
                    $(this).addClass("wysiwyg-button-hover");
                };
	
                this.ui.appendControls = function () {
                    var ui = this,
                    self = this.self,
                    controls = self.parseControls(),
                    hasVisibleControls	= true, // to prevent separator before first item
                    groups = [],
                    controlsByGroup = {},
                    i,
                    currentGroupIndex, // jslint wants all vars at top of function
                    iterateGroup = function (controlName, control) {
                        if (control.groupIndex && currentGroupIndex !== control.groupIndex) {
                            currentGroupIndex = control.groupIndex;
                            hasVisibleControls = false;
                        }
	
                        if (!control.visible) {
                            return;
                        }
	
                        if (!hasVisibleControls) {
                            ui.appendItemSeparator();
                            hasVisibleControls = true;
                        }
	
                        if (control.custom) {
                            ui.appendItemCustom(controlName, control);
                        } else {
                            ui.appendItem(controlName, control);
                        }
                    };
	
                    $.each(controls, function (name, c) {
                        var index = "empty";
	
                        if (undefined !== c.groupIndex) {
                            if ("" === c.groupIndex) {
                                index = "empty";
                            } else {
                                index = c.groupIndex;
                            }
                        }
	
                        if (undefined === controlsByGroup[index]) {
                            groups.push(index);
                            controlsByGroup[index] = {};
                        }
                        controlsByGroup[index][name] = c;
                    });
	
                    groups.sort(function (a, b) {
                        if ("number" === typeof (a) && typeof (a) === typeof (b)) {
                            return (a - b);
                        } else {
                            a = a.toString();
                            b = b.toString();
	
                            if (a > b) {
                                return 1;
                            }
	
                            if (a === b) {
                                return 0;
                            }
	
                            return -1;
                        }
                    });
	
                    if (0 < groups.length) {
                        // set to first index in groups to proper placement of separator
                        currentGroupIndex = groups[0];
                    }
	
                    for (i = 0; i < groups.length; i += 1) {
                        $.each(controlsByGroup[groups[i]], iterateGroup);
                    }
                };
	
                this.ui.appendItem = function (name, control) {
                    var self = this.self,
                    className = control.className || control.command || name || "empty",
                    tooltip = control.tooltip || control.command || name || "";
	
                    return $('<li role="menuitem" unselectable="on">' + (className) + "</li>")
                    .addClass(className)
                    .attr("title", tooltip)
                    .hover(this.addHoverClass, this.removeHoverClass)
                    .click(function () {
                        if ($(this).hasClass("disabled")) {
                            return false;
                        }
	
                        self.triggerControl.apply(self, [name, control]);
	
                        this.blur();
                        self.ui.returnRange();
                        self.ui.focus();
                        return true;
                    })
                    .appendTo(self.ui.toolbar);
                };
	
                this.ui.appendItemCustom = function (name, control) {
                    var self = this.self,
                    tooltip = control.tooltip || control.command || name || "";
	
                    if (control.callback) {
                        $(window).bind("trigger-" + name + ".wysiwyg", control.callback);
                    }
	
                    return $('<li role="menuitem" unselectable="on" style="background: url(\'' + control.icon + '\') no-repeat;"></li>')
                    .addClass("custom-command-" + name)
                    .addClass("wysiwyg-custom-command")
                    .addClass(name)
                    .attr("title", tooltip)
                    .hover(this.addHoverClass, this.removeHoverClass)
                    .click(function () {
                        if ($(this).hasClass("disabled")) {
                            return false;
                        }
	
                        self.triggerControl.apply(self, [name, control]);
	
                        this.blur();
                        self.ui.returnRange();
                        self.ui.focus();
	
                        self.triggerControlCallback(name);
                        return true;
                    })
                    .appendTo(self.ui.toolbar);
                };
	
                this.ui.appendItemSeparator = function () {
                    var self = this.self;
                    return $('<li role="separator" class="separator"></li>').appendTo(self.ui.toolbar);
                };
	
                this.autoSaveFunction = function () {
                    this.saveContent();
                };
	
                this.ui.checkTargets = function (element) {
                    var self = this.self;
	
                    $.each(self.options.controls, function (name, control) {
                        var className = control.className || control.command || name || "empty",
                        tags,
                        elm,
                        css,
                        el,
                        checkActiveStatus = function (cssProperty, cssValue) {
                            var handler;
	
                            if ("function" === typeof (cssValue)) {
                                handler = cssValue;
                                if (handler(el.css(cssProperty).toString().toLowerCase(), self)) {
                                    self.ui.toolbar.find("." + className).addClass("active");
                                }
                            } else {
                                if (el.css(cssProperty).toString().toLowerCase() === cssValue) {
                                    self.ui.toolbar.find("." + className).addClass("active");
                                }
                            }
                        };
	
                        if ("fullscreen" !== className) {
                            self.ui.toolbar.find("." + className).removeClass("active");
                        }
	
                        if (control.tags || (control.options && control.options.tags)) {
                            tags = control.tags || (control.options && control.options.tags);
	
                            elm = element;
                            while (elm) {
                                if (elm.nodeType !== 1) {
                                    break;
                                }
	
                                if ($.inArray(elm.tagName.toLowerCase(), tags) !== -1) {
                                    self.ui.toolbar.find("." + className).addClass("active");
                                }
	
                                elm = elm.parentNode;
                            }
                        }
	
                        if (control.css || (control.options && control.options.css)) {
                            css = control.css || (control.options && control.options.css);
                            el = $(element);
	
                            while (el) {
                                if (el[0].nodeType !== 1) {
                                    break;
                                }
                                $.each(css, checkActiveStatus);
	
                                el = el.parent();
                            }
                        }
                    });
                };
	
                this.ui.designMode = function () {
                    var attempts = 3,
                    self = this.self,
                    runner;
                    runner = function (attempts) {
                        if ("on" === self.editorDoc.designMode) {
                            if (self.timers.designMode) {
                                window.clearTimeout(self.timers.designMode);
                            }
	
                            // IE needs to reget the document element (this.editorDoc) after designMode was set
                            if (self.innerDocument() !== self.editorDoc) {
                                self.ui.initFrame();
                            }
	
                            return;
                        }
	
                        try {
                            self.editorDoc.designMode = "on";
                        } catch (e) {
                        }
	
                        attempts -= 1;
                        if (attempts > 0) {
                            self.timers.designMode = window.setTimeout(function () {
                                runner(attempts);
                            }, 100);
                        }
                    };
	
                    runner(attempts);
                };
	
                this.destroy = function () {
                    this.isDestroyed = true;
	
                    var i, $form = this.element.closest("form");
	
                    for (i = 0; i < this.timers.length; i += 1) {
                        window.clearTimeout(this.timers[i]);
                    }
	
                    // Remove bindings
                    $form.unbind(".wysiwyg");
                    this.element.remove();
                    $.removeData(this.original, "wysiwyg");
                    $(this.original).show();
                    return this;
                };
	
                this.getRangeText = function () {
                    var r = this.getInternalRange();
	
                    if (r.toString) {
                        r = r.toString();
                    } else if (r.text) {	// IE
                        r = r.text;
                    }
	
                    return r;
                };
                //not used?
                this.execute = function (command, arg) {
                    if (typeof (arg) === "undefined") {
                        arg = null;
                    }
                    this.editorDoc.execCommand(command, false, arg);
                };
	
                this.extendOptions = function (options) {
                    var controls = {};
	
                    /**
				 * If the user set custom controls, we catch it, and merge with the
				 * defaults controls later.
				 */
                    if ("object" === typeof options.controls) {
                        controls = options.controls;
                        delete options.controls;
                    }
	
                    options = $.extend(true, {}, this.defaults, options);
                    options.controls = $.extend(true, {}, controls, this.controls, controls);
	
                    if (options.rmUnusedControls) {
                        $.each(options.controls, function (controlName) {
                            if (!controls[controlName]) {
                                delete options.controls[controlName];
                            }
                        });
                    }
	
                    return options;
                };
	
                this.ui.focus = function () {
                    var self = this.self;
	
                    self.editor.get(0).contentWindow.focus();
                    return self;
                };
	
                this.ui.returnRange = function () {
                    var self = this.self, sel;
	
                    if (self.savedRange !== null) {
                        if (window.getSelection) { //non IE and there is already a selection
                            sel = window.getSelection();
                            if (sel.rangeCount > 0) {
                                sel.removeAllRanges();
                            }
                            try {
                                sel.addRange(self.savedRange);
                            } catch (e) {
                                console.error(e);
                            }
                        } else if (window.document.createRange) { // non IE and no selection
                            window.getSelection().addRange(self.savedRange);
                        } else if (window.document.selection) { //IE
                            self.savedRange.select();
                        }
	
                        self.savedRange = null;
                    }
                };
	
                this.increaseFontSize = function () {
                    if ($.browser.mozilla || $.browser.opera) {
                        this.editorDoc.execCommand('increaseFontSize', false, null);
                    } else if ($.browser.safari) {
                        var newNode = this.editorDoc.createElement('big');
                        this.getInternalRange().surroundContents(newNode);
                    } else {
                        console.error("Internet Explorer?");
                    }
                };
	
                this.decreaseFontSize = function () {
                    if ($.browser.mozilla || $.browser.opera) {
                        this.editorDoc.execCommand('decreaseFontSize', false, null);
                    } else if ($.browser.safari) {
                        var newNode = this.editorDoc.createElement('small');
                        this.getInternalRange().surroundContents(newNode);
                    } else {
                        console.error("Internet Explorer?");
                    }
                };
	
                this.getContent = function () {
                    if (this.viewHTML) {
                        this.setContent(this.original.value);
                    }
                    return this.events.filter('getContent', this.editorDoc.body.innerHTML);
                };
			
                /**
			 * A jWysiwyg specific event system.
			 *
			 * Example:
			 * 
			 * $("#editor").getWysiwyg().events.bind("getContent", function (orig) {
			 *     return "<div id='content'>"+orgi+"</div>";
			 * });
			 * 
			 * This makes it so that when ever getContent is called, it is wrapped in a div#content.
			 */
                this.events = {
                    _events : {},
				
                    /**
				 * Similar to jQuery's bind, but for jWysiwyg only.
				 */
                    bind : function (eventName, callback) {
                        if (typeof (this._events.eventName) !== "object") {
                            this._events[eventName] = [];
                        }
                        this._events[eventName].push(callback);
                    },
				
                    /**
				 * Similar to jQuery's trigger, but for jWysiwyg only.
				 */
                    trigger : function (eventName, args) {
                        if (typeof (this._events.eventName) === "object") {
                            var editor = this.editor;
                            $.each(this._events[eventName], function (k, v) {
                                if (typeof (v) === "function") {
                                    v.apply(editor, args);
                                }
                            });
                        }
                    },
				
                    /**
				 * This "filters" `originalText` by passing it as the first argument to every callback
				 * with the name `eventName` and taking the return value and passing it to the next function.
				 *
				 * This function returns the result after all the callbacks have been applied to `originalText`.
				 */
                    filter : function (eventName, originalText) {
                        if (typeof (this._events[eventName]) === "object") {
                            var editor = this.editor,
                            args = Array.prototype.slice.call(arguments, 1);
	
                            $.each(this._events[eventName], function (k, v) {
                                if (typeof (v) === "function") {
                                    originalText = v.apply(editor, args);
                                }
                            });
                        }
                        return originalText;
                    }
                };
	
                this.getElementByAttributeValue = function (tagName, attributeName, attributeValue) {
                    var i, value, elements = this.editorDoc.getElementsByTagName(tagName);
	
                    for (i = 0; i < elements.length; i += 1) {
                        value = elements[i].getAttribute(attributeName);
	
                        if ($.browser.msie) {
                            /** IE add full path, so I check by the last chars. */
                            value = value.substr(value.length - attributeValue.length);
                        }
	
                        if (value === attributeValue) {
                            return elements[i];
                        }
                    }
	
                    return false;
                };
	
                this.getInternalRange = function () {
                    var selection = this.getInternalSelection();
	
                    if (!selection) {
                        return null;
                    }
	
                    if (selection.rangeCount && selection.rangeCount > 0) { // w3c
                        return selection.getRangeAt(0);
                    } else if (selection.createRange) { // ie
                        return selection.createRange();
                    }
	
                    return null;
                };
	
                this.getInternalSelection = function () {
                    // firefox: document.getSelection is deprecated
                    if (this.editor.get(0).contentWindow) {
                        if (this.editor.get(0).contentWindow.getSelection) {
                            return this.editor.get(0).contentWindow.getSelection();
                        }
                        if (this.editor.get(0).contentWindow.selection) {
                            return this.editor.get(0).contentWindow.selection;
                        }
                    }
                    if (this.editorDoc.getSelection) {
                        return this.editorDoc.getSelection();
                    }
                    if (this.editorDoc.selection) {
                        return this.editorDoc.selection;
                    }
	
                    return null;
                };
	
                this.getRange = function () {
                    var selection = this.getSelection();
	
                    if (!selection) {
                        return null;
                    }
	
                    if (selection.rangeCount && selection.rangeCount > 0) { // w3c
                        selection.getRangeAt(0);
                    } else if (selection.createRange) { // ie
                        return selection.createRange();
                    }
	
                    return null;
                };
	
                this.getSelection = function () {
                    return (window.getSelection) ? window.getSelection() : window.document.selection;
                };
	
                this.ui.grow = function () {
                    var self = this.self,
                    innerBody = $(self.editorDoc.body),
                    innerHeight = $.browser.msie ? innerBody[0].scrollHeight : innerBody.height() + 2 + 20, // 2 - borders, 20 - to prevent content jumping on grow
                    minHeight = self.ui.initialHeight,
                    height = Math.max(innerHeight, minHeight);
	
                    height = Math.min(height, self.options.maxHeight);
	
                    self.editor.attr("scrolling", height < self.options.maxHeight ? "no" : "auto"); // hide scrollbar firefox
                    innerBody.css("overflow", height < self.options.maxHeight ? "hidden" : ""); // hide scrollbar chrome
	
                    self.editor.get(0).height = height;
	
                    return self;
                };
	
                this.init = function (element, options) {
                    var self = this,
                    $form = $(element).closest("form"),
                    newX = element.width || element.clientWidth || 0,
                    newY = element.height || element.clientHeight || 0
                    ;
	
                    this.options	= this.extendOptions(options);
                    this.original	= element;
                    this.ui.toolbar	= $(this.options.toolbarHtml);
	
                    if ($.browser.msie && parseInt($.browser.version, 10) < 8) {
                        this.options.autoGrow = false;
                    }
	
                    if (newX === 0 && element.cols) {
                        newX = (element.cols * 8) + 21;
                    }
                    if (newY === 0 && element.rows) {
                        newY = (element.rows * 16) + 16;
                    }
	
                    this.editor = $(window.location.protocol === "https:" ? '<iframe src="javascript:false;"></iframe>' : "<iframe></iframe>").attr("frameborder", "0");
	
                    if (this.options.iFrameClass) {
                        this.editor.addClass(this.options.iFrameClass);
                    } else {
                        this.editor.css({
                            minHeight: (newY - 6).toString() + "px",
                            // fix for issue 12 ( http://github.com/akzhan/jwysiwyg/issues/issue/12 )
                            width: (newX > 50) ? (newX - 8).toString() + "px" : ""
                        });
                        if ($.browser.msie && parseInt($.browser.version, 10) < 7) {
                            this.editor.css("height", newY.toString() + "px");
                        }
                    }
                    /**
				 * http://code.google.com/p/jwysiwyg/issues/detail?id=96
				 */
                    this.editor.attr("tabindex", $(element).attr("tabindex"));
	
                    this.element = $("<div/>").addClass("wysiwyg");
	
                    if (!this.options.iFrameClass) {
                        this.element.css({
                            width: (newX > 0) ? newX.toString() + "px" : "100%"
                        });
                    }
	
                    $(element).hide().before(this.element);
	
                    this.viewHTML = false;
	
                    /**
				 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=52
				 */
                    this.initialContent = $(element).val();
                    this.ui.initFrame();
	
                    if (this.options.resizeOptions && $.fn.resizable) {
                        this.element.resizable($.extend(true, {
                            alsoResize: this.editor
                        }, this.options.resizeOptions));
                    }
	
                    if (this.options.autoSave) {
                        $form.bind("submit.wysiwyg", function () {
                            self.autoSaveFunction();
                        });
                    }
	
                    $form.bind("reset.wysiwyg", function () {
                        self.resetFunction();
                    });
                };
	
                this.ui.initFrame = function () {
                    var self = this.self,
                    stylesheet,
                    growHandler,
                    saveHandler;
	
                    self.ui.appendControls();
                    self.element.append(self.ui.toolbar)
                    .append($("<div><!-- --></div>")
                        .css({
                            clear: "both"
                        }))
                    .append(self.editor);
	
                    self.editorDoc = self.innerDocument();
	
                    if (self.isDestroyed) {
                        return null;
                    }
	
                    self.ui.designMode();
                    self.editorDoc.open();
                    self.editorDoc.write(
                        self.options.html
                        /**
						 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=144
						 */
                        .replace(/INITIAL_CONTENT/, function () {
                            return self.wrapInitialContent();
                        })
                        );
                    self.editorDoc.close();
	
                    $.wysiwyg.plugin.bind(self);
	
                    $(self.editorDoc).trigger("initFrame.wysiwyg");
	
                    $(self.editorDoc).bind("click.wysiwyg", function (event) {
                        self.ui.checkTargets(event.target ? event.target : event.srcElement);
                    });
	
                    /**
				 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20
				 */
                    $(self.original).focus(function () {
                        if ($(this).filter(":visible")) {
                            return;
                        }
                        self.ui.focus();
                    });
	
                    $(self.editorDoc).keydown(function (event) {
                        var emptyContentRegex;
                        if (event.keyCode === 8) { // backspace
                            emptyContentRegex = /^<([\w]+)[^>]*>(<br\/?>)?<\/\1>$/;
                            if (emptyContentRegex.test(self.getContent())) { // if content is empty
                                event.stopPropagation(); // prevent remove single empty tag
                                return false;
                            }
                        }
                        return true;
                    });
	
                    if (!$.browser.msie) {
                        $(self.editorDoc).keydown(function (event) {
                            var controlName;
	
                            /* Meta for Macs. tom@punkave.com */
                            if (event.ctrlKey || event.metaKey) {
                                for (controlName in self.controls) {
                                    if (self.controls[controlName].hotkey && self.controls[controlName].hotkey.ctrl) {
                                        if (event.keyCode === self.controls[controlName].hotkey.key) {
                                            self.triggerControl.apply(self, [controlName, self.controls[controlName]]);
	
                                            return false;
                                        }
                                    }
                                }
                            }
	
                            return true;
                        });
                    } else if (self.options.brIE) {
                        $(self.editorDoc).keydown(function (event) {
                            if (event.keyCode === 13) {
                                var rng = self.getRange();
                                rng.pasteHTML("<br/>");
                                rng.collapse(false);
                                rng.select();
	
                                return false;
                            }
	
                            return true;
                        });
                    }
	
                    if (self.options.plugins.rmFormat.rmMsWordMarkup) {
                        $(self.editorDoc).bind("keyup.wysiwyg", function (event) {
                            if (event.ctrlKey || event.metaKey) {
                                // CTRL + V (paste)
                                if (86 === event.keyCode) {
                                    if ($.wysiwyg.rmFormat) {
                                        if ("object" === typeof (self.options.plugins.rmFormat.rmMsWordMarkup)) {
                                            $.wysiwyg.rmFormat.run(self, {
                                                rules: {
                                                    msWordMarkup: self.options.plugins.rmFormat.rmMsWordMarkup
                                                }
                                            });
                                        } else {
                                            $.wysiwyg.rmFormat.run(self, {
                                                rules: {
                                                    msWordMarkup: {
                                                        enabled: true
                                                    }
                                                }
                                            });
                                        }
                                    }
                                }
                            }
                        });
                    }
	
                    if (self.options.autoSave) {
                        $(self.editorDoc).keydown(function () {
                            self.autoSaveFunction();
                        })
                        .keyup(function () {
                            self.autoSaveFunction();
                        })
                        .mousedown(function () {
                            self.autoSaveFunction();
                        })
                        .bind($.support.noCloneEvent ? "input.wysiwyg" : "paste.wysiwyg", function () {
                            self.autoSaveFunction();
                        });
                    }
	
                    if (self.options.autoGrow) {
                        if (self.options.initialMinHeight !== null) {
                            self.ui.initialHeight = self.options.initialMinHeight;
                        } else {
                            self.ui.initialHeight = $(self.editorDoc).height();
                        }
                        $(self.editorDoc.body).css("border", "1px solid white"); // cancel margin collapsing
	
                        growHandler = function () {
                            self.ui.grow();
                        };
	
                        $(self.editorDoc).keyup(growHandler);
                        $(self.editorDoc).bind("editorRefresh.wysiwyg", growHandler);
	
                        // fix when content height > textarea height
                        self.ui.grow();
                    }
	
                    if (self.options.css) {
                        if (String === self.options.css.constructor) {
                            if ($.browser.msie) {
                                stylesheet = self.editorDoc.createStyleSheet(self.options.css);
                                $(stylesheet).attr({
                                    "media":	"all"
                                });
                            } else {
                                stylesheet = $("<link/>").attr({
                                    "href":		self.options.css,
                                    "media":	"all",
                                    "rel":		"stylesheet",
                                    "type":		"text/css"
                                });
	
                                $(self.editorDoc).find("head").append(stylesheet);
                            }
                        } else {
                            self.timers.initFrame_Css = window.setTimeout(function () {
                                $(self.editorDoc.body).css(self.options.css);
                            }, 0);
                        }
                    }
	
                    if (self.initialContent.length === 0) {
                        if ("function" === typeof (self.options.initialContent)) {
                            self.setContent(self.options.initialContent());
                        } else {
                            self.setContent(self.options.initialContent);
                        }
                    }
	
                    if (self.options.maxLength > 0) {
                        $(self.editorDoc).keydown(function (event) {
                            if ($(self.editorDoc).text().length >= self.options.maxLength && $.inArray(event.which, self.validKeyCodes) === -1) {
                                event.preventDefault();
                            }
                        });
                    }
				
                    // Support event callbacks
                    $.each(self.options.events, function (key, handler) {
                        $(self.editorDoc).bind(key + ".wysiwyg", function (event) {
                            // Trigger event handler, providing the event and api to 
                            // support additional functionality.
                            handler.apply(self.editorDoc, [event, self]);
                        });
                    });
	
                    // restores selection properly on focus
                    if ($.browser.msie) {
                        // Event chain: beforedeactivate => focusout => blur.
                        // Focusout & blur fired too late to handle internalRange() in dialogs.
                        // When clicked on input boxes both got range = null
                        $(self.editorDoc).bind("beforedeactivate.wysiwyg", function () {
                            self.savedRange = self.getInternalRange();
                        });
                    } else {
                        $(self.editorDoc).bind("blur.wysiwyg", function () {
                            self.savedRange = self.getInternalRange();
                        });
                    }
	
                    $(self.editorDoc.body).addClass("wysiwyg");
                    if (self.options.events && self.options.events.save) {
                        saveHandler = self.options.events.save;
	
                        $(self.editorDoc).bind("keyup.wysiwyg", saveHandler);
                        $(self.editorDoc).bind("change.wysiwyg", saveHandler);
	
                        if ($.support.noCloneEvent) {
                            $(self.editorDoc).bind("input.wysiwyg", saveHandler);
                        }
                        else {
                            $(self.editorDoc).bind("paste.wysiwyg", saveHandler);
                            $(self.editorDoc).bind("cut.wysiwyg", saveHandler);
                        }
                    }
				
                    /**
				 * XHTML5 {@link https://github.com/akzhan/jwysiwyg/issues/152}
				 */
                    if (self.options.xhtml5 && self.options.unicode) {
                        var replacements = {
                            ne:8800,
                            le:8804,
                            para:182,
                            xi:958,
                            darr:8595,
                            nu:957,
                            oacute:243,
                            Uacute:218,
                            omega:969,
                            prime:8242,
                            pound:163,
                            igrave:236,
                            thorn:254,
                            forall:8704,
                            emsp:8195,
                            lowast:8727,
                            brvbar:166,
                            alefsym:8501,
                            nbsp:160,
                            delta:948,
                            clubs:9827,
                            lArr:8656,
                            Omega:937,
                            Auml:196,
                            cedil:184,
                            and:8743,
                            plusmn:177,
                            ge:8805,
                            raquo:187,
                            uml:168,
                            equiv:8801,
                            laquo:171,
                            rdquo:8221,
                            Epsilon:917,
                            divide:247,
                            fnof:402,
                            chi:967,
                            Dagger:8225,
                            iacute:237,
                            rceil:8969,
                            sigma:963,
                            Oslash:216,
                            acute:180,
                            frac34:190,
                            lrm:8206,
                            upsih:978,
                            Scaron:352,
                            part:8706,
                            exist:8707,
                            nabla:8711,
                            image:8465,
                            prop:8733,
                            zwj:8205,
                            omicron:959,
                            aacute:225,
                            Yuml:376,
                            Yacute:221,
                            weierp:8472,
                            rsquo:8217,
                            otimes:8855,
                            kappa:954,
                            thetasym:977,
                            harr:8596,
                            Ouml:214,
                            Iota:921,
                            ograve:242,
                            sdot:8901,
                            copy:169,
                            oplus:8853,
                            acirc:226,
                            sup:8835,
                            zeta:950,
                            Iacute:205,
                            Oacute:211,
                            crarr:8629,
                            Nu:925,
                            bdquo:8222,
                            lsquo:8216,
                            apos:39,
                            Beta:914,
                            eacute:233,
                            egrave:232,
                            lceil:8968,
                            Kappa:922,
                            piv:982,
                            Ccedil:199,
                            ldquo:8220,
                            Xi:926,
                            cent:162,
                            uarr:8593,
                            hellip:8230,
                            Aacute:193,
                            ensp:8194,
                            sect:167,
                            Ugrave:217,
                            aelig:230,
                            ordf:170,
                            curren:164,
                            sbquo:8218,
                            macr:175,
                            Phi:934,
                            Eta:919,
                            rho:961,
                            Omicron:927,
                            sup2:178,
                            euro:8364,
                            aring:229,
                            Theta:920,
                            mdash:8212,
                            uuml:252,
                            otilde:245,
                            eta:951,
                            uacute:250,
                            rArr:8658,
                            nsub:8836,
                            agrave:224,
                            notin:8713,
                            ndash:8211,
                            Psi:936,
                            Ocirc:212,
                            sube:8838,
                            szlig:223,
                            micro:181,
                            not:172,
                            sup1:185,
                            middot:183,
                            iota:953,
                            ecirc:234,
                            lsaquo:8249,
                            thinsp:8201,
                            sum:8721,
                            ntilde:241,
                            scaron:353,
                            cap:8745,
                            atilde:227,
                            lang:10216,
                            __replacement:65533,
                            isin:8712,
                            gamma:947,
                            Euml:203,
                            ang:8736,
                            upsilon:965,
                            Ntilde:209,
                            hearts:9829,
                            Alpha:913,
                            Tau:932,
                            spades:9824,
                            dagger:8224,
                            THORN:222,
                            "int":8747,
                            lambda:955,
                            Eacute:201,
                            Uuml:220,
                            infin:8734,
                            rlm:8207,
                            Aring:197,
                            ugrave:249,
                            Egrave:200,
                            Acirc:194,
                            rsaquo:8250,
                            ETH:208,
                            oslash:248,
                            alpha:945,
                            Ograve:210,
                            Prime:8243,
                            mu:956,
                            ni:8715,
                            real:8476,
                            bull:8226,
                            beta:946,
                            icirc:238,
                            eth:240,
                            prod:8719,
                            larr:8592,
                            ordm:186,
                            perp:8869,
                            Gamma:915,
                            reg:174,
                            ucirc:251,
                            Pi:928,
                            psi:968,
                            tilde:732,
                            asymp:8776,
                            zwnj:8204,
                            Agrave:192,
                            deg:176,
                            AElig:198,
                            times:215,
                            Delta:916,
                            sim:8764,
                            Otilde:213,
                            Mu:924,
                            uArr:8657,
                            circ:710,
                            theta:952,
                            Rho:929,
                            sup3:179,
                            diams:9830,
                            tau:964,
                            Chi:935,
                            frac14:188,
                            oelig:339,
                            shy:173,
                            or:8744,
                            dArr:8659,
                            phi:966,
                            iuml:239,
                            Lambda:923,
                            rfloor:8971,
                            iexcl:161,
                            cong:8773,
                            ccedil:231,
                            Icirc:206,
                            frac12:189,
                            loz:9674,
                            rarr:8594,
                            cup:8746,
                            radic:8730,
                            frasl:8260,
                            euml:235,
                            OElig:338,
                            hArr:8660,
                            Atilde:195,
                            Upsilon:933,
                            there4:8756,
                            ouml:246,
                            oline:8254,
                            Ecirc:202,
                            yacute:253,
                            auml:228,
                            permil:8240,
                            sigmaf:962,
                            iquest:191,
                            empty:8709,
                            pi:960,
                            Ucirc:219,
                            supe:8839,
                            Igrave:204,
                            yen:165,
                            rang:10217,
                            trade:8482,
                            lfloor:8970,
                            minus:8722,
                            Zeta:918,
                            sub:8834,
                            epsilon:949,
                            yuml:255,
                            Sigma:931,
                            Iuml:207,
                            ocirc:244
                        };
                        self.events.bind("getContent", function (text) {
                            return text.replace(/&(?:amp;)?(?!amp|lt|gt|quot)([a-z][a-z0-9]*);/gi, function (str, p1) {
                                if (!replacements[p1]) {
                                    p1 = p1.toLowerCase();
                                    if (!replacements[p1]) {
                                        p1 = "__replacement";
                                    }
                                }
							
                                var num = replacements[p1];
                                /* Numeric return if ever wanted: return replacements[p1] ? "&#"+num+";" : ""; */
                                return String.fromCharCode(num);
                            });
                        });
                    }
                };
	
                this.innerDocument = function () {
                    var element = this.editor.get(0);
	
                    if (element.nodeName.toLowerCase() === "iframe") {
                        if (element.contentDocument) {				// Gecko
                            return element.contentDocument;
                        } else if (element.contentWindow) {			// IE
                            return element.contentWindow.document;
                        }
	
                        if (this.isDestroyed) {
                            return null;
                        }
	
                        console.error("Unexpected error in innerDocument");
	
                    /*
					 return ( $.browser.msie )
					 ? document.frames[element.id].document
					 : element.contentWindow.document // contentDocument;
					 */
                    }
	
                    return element;
                };
	
                this.insertHtml = function (szHTML) {
                    var img, range;
	
                    if (!szHTML || szHTML.length === 0) {
                        return this;
                    }
	
                    if ($.browser.msie) {
                        this.ui.focus();
                        this.editorDoc.execCommand("insertImage", false, "#jwysiwyg#");
                        img = this.getElementByAttributeValue("img", "src", "#jwysiwyg#");
                        if (img) {
                            $(img).replaceWith(szHTML);
                        }
                    } else {
                        if ($.browser.mozilla) { // @link https://github.com/akzhan/jwysiwyg/issues/50
                            if (1 === $(szHTML).length) {
                                range = this.getInternalRange();
                                range.deleteContents();
                                range.insertNode($(szHTML).get(0));
                            } else {
                                this.editorDoc.execCommand("insertHTML", false, szHTML);
                            }
                        } else {
                            if (!this.editorDoc.execCommand("insertHTML", false, szHTML)) {
                                this.editor.focus();
                                /* 
							if (window.getSelection) {
							} else {
							}
							this.editor.focus();
							*/
                                this.editorDoc.execCommand("insertHTML", false, szHTML);
                            }
                        }
                    }
	
                    this.saveContent();
				
                    return this;
                };
	
                this.parseControls = function () {
                    var self = this;
	
                    $.each(this.options.controls, function (controlName, control) {
                        $.each(control, function (propertyName) {
                            if (-1 === $.inArray(propertyName, self.availableControlProperties)) {
                                throw controlName + '["' + propertyName + '"]: property "' + propertyName + '" not exists in Wysiwyg.availableControlProperties';
                            }
                        });
                    });
	
                    if (this.options.parseControls) {
                        return this.options.parseControls.call(this);
                    }
	
                    return this.options.controls;
                };
	
                this.removeFormat = function () {
                    if ($.browser.msie) {
                        this.ui.focus();
                    }
	
                    if (this.options.removeHeadings) {
                        this.editorDoc.execCommand("formatBlock", false, "<p>"); // remove headings
                    }
	
                    this.editorDoc.execCommand("removeFormat", false, null);
                    this.editorDoc.execCommand("unlink", false, null);
	
                    if ($.wysiwyg.rmFormat && $.wysiwyg.rmFormat.enabled) {
                        if ("object" === typeof (this.options.plugins.rmFormat.rmMsWordMarkup)) {
                            $.wysiwyg.rmFormat.run(this, {
                                rules: {
                                    msWordMarkup: this.options.plugins.rmFormat.rmMsWordMarkup
                                }
                            });
                        } else {
                            $.wysiwyg.rmFormat.run(this, {
                                rules: {
                                    msWordMarkup: {
                                        enabled: true
                                    }
                                }
                            });
                        }
                    }
	
                    return this;
                };
	
                this.ui.removeHoverClass = function () {
                    $(this).removeClass("wysiwyg-button-hover");
                };
	
                this.resetFunction = function () {
                    this.setContent(this.initialContent);
                };
	
                this.saveContent = function () {
                    if (this.viewHTML)
                    {
                        return; // no need
                    }
                    if (this.original) {
                        var content, newContent;
	
                        content = this.getContent();
	
                        if (this.options.rmUnwantedBr) {
                            content = content.replace(/<br\/?>$/, "");
                        }
	
                        if (this.options.replaceDivWithP) {
                            newContent = $("<div/>").addClass("temp").append(content);
	
                            newContent.children("div").each(function () {
                                var element = $(this), p = element.find("p"), i;
	
                                if (0 === p.length) {
                                    p = $("<p></p>");
	
                                    if (this.attributes.length > 0) {
                                        for (i = 0; i < this.attributes.length; i += 1) {
                                            p.attr(this.attributes[i].name, element.attr(this.attributes[i].name));
                                        }
                                    }
	
                                    p.append(element.html());
	
                                    element.replaceWith(p);
                                }
                            });
						
                            content = newContent.html();
                        }
	
                        $(this.original).val(content);
	
                        if (this.options.events && this.options.events.save) {
                            this.options.events.save.call(this);
                        }
                    }
	
                    return this;
                };
	
                this.setContent = function (newContent) {
                    this.editorDoc.body.innerHTML = newContent;
                    this.saveContent();
	
                    return this;
                };
	
                this.triggerControl = function (name, control) {
                    var cmd = control.command || name,
                    args = control["arguments"] || [];
	
                    if (control.exec) {
                        control.exec.apply(this);
                    } else {
                        this.ui.focus();
                        this.ui.withoutCss();
                        // when click <Cut>, <Copy> or <Paste> got "Access to XPConnect service denied" code: "1011"
                        // in Firefox untrusted JavaScript is not allowed to access the clipboard
                        try {
                            this.editorDoc.execCommand(cmd, false, args);
                        } catch (e) {
                            console.error(e);
                        }
                    }
	
                    if (this.options.autoSave) {
                        this.autoSaveFunction();
                    }
                };
	
                this.triggerControlCallback = function (name) {
                    $(window).trigger("trigger-" + name + ".wysiwyg", [this]);
                };
	
                this.ui.withoutCss = function () {
                    var self = this.self;
	
                    if ($.browser.mozilla) {
                        try {
                            self.editorDoc.execCommand("styleWithCSS", false, false);
                        } catch (e) {
                            try {
                                self.editorDoc.execCommand("useCSS", false, true);
                            } catch (e2) {
                            }
                        }
                    }
	
                    return self;
                };
	
                this.wrapInitialContent = function () {
                    var content = this.initialContent,
                    found = content.match(/<\/?p>/gi);
	
                    if (!found) {
                        return "<p>" + content + "</p>";
                    } else {
                    }
	
                    return content;
                };
            }
	
            /*
		 * Wysiwyg namespace: public properties and methods
		 */
            $.wysiwyg = {
                messages: {
                    noObject: "Something goes wrong, check object"
                },
	
                /**
			 * Custom control support by Alec Gorge ( http://github.com/alecgorge )
			 */
                addControl: function (object, name, settings) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg"),
                        customControl = {},
                        toolbar;
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        customControl[name] = $.extend(true, {
                            visible: true, 
                            custom: true
                        }, settings);
                        $.extend(true, oWysiwyg.options.controls, customControl);
	
                        // render new toolbar
                        toolbar = $(oWysiwyg.options.toolbarHtml);
                        oWysiwyg.ui.toolbar.replaceWith(toolbar);
                        oWysiwyg.ui.toolbar = toolbar;
                        oWysiwyg.ui.appendControls();
                    });
                },
	
                clear: function (object) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg");
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        oWysiwyg.setContent("");
                    });
                },
	
                console: console, // let our console be available for extensions
	
                destroy: function (object) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg");
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        oWysiwyg.destroy();
                    });
                },
	
                "document": function (object) {
                    // no chains because of return
                    var oWysiwyg = object.data("wysiwyg");
	
                    if (!oWysiwyg) {
                        return undefined;
                    }
	
                    return $(oWysiwyg.editorDoc);
                },
	
                getContent: function (object) {
                    // no chains because of return
                    var oWysiwyg = object.data("wysiwyg");
	
                    if (!oWysiwyg) {
                        return undefined;
                    }
	
                    return oWysiwyg.getContent();
                },
	
                init: function (object, options) {
                    return object.each(function () {
                        var opts = $.extend(true, {}, options),
                        obj;
	
                        // :4fun:
                        // remove this textarea validation and change line in this.saveContent function
                        // $(this.original).val(content); to $(this.original).html(content);
                        // now you can make WYSIWYG editor on h1, p, and many more tags
                        if (("textarea" !== this.nodeName.toLowerCase()) || $(this).data("wysiwyg")) {
                            return;
                        }
	
                        obj = new Wysiwyg();
                        obj.init(this, opts);
                        $.data(this, "wysiwyg", obj);
	
                        $(obj.editorDoc).trigger("afterInit.wysiwyg");
                    });
                },
	
                insertHtml: function (object, szHTML) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg");
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        oWysiwyg.insertHtml(szHTML);
                    });
                },
	
                plugin: {
                    listeners: {},
	
                    bind: function (Wysiwyg) {
                        var self = this;
	
                        $.each(this.listeners, function (action, handlers) {
                            var i, plugin;
	
                            for (i = 0; i < handlers.length; i += 1) {
                                plugin = self.parseName(handlers[i]);
	
                                $(Wysiwyg.editorDoc).bind(action + ".wysiwyg", {
                                    plugin: plugin
                                }, function (event) {
                                    $.wysiwyg[event.data.plugin.name][event.data.plugin.method].apply($.wysiwyg[event.data.plugin.name], [Wysiwyg]);
                                });
                            }
                        });
                    },
	
                    exists: function (name) {
                        var plugin;
	
                        if ("string" !== typeof (name)) {
                            return false;
                        }
	
                        plugin = this.parseName(name);
	
                        if (!$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method]) {
                            return false;
                        }
	
                        return true;
                    },
	
                    listen: function (action, handler) {
                        var plugin;
	
                        plugin = this.parseName(handler);
	
                        if (!$.wysiwyg[plugin.name] || !$.wysiwyg[plugin.name][plugin.method]) {
                            return false;
                        }
	
                        if (!this.listeners[action]) {
                            this.listeners[action] = [];
                        }
	
                        this.listeners[action].push(handler);
	
                        return true;
                    },
	
                    parseName: function (name) {
                        var elements;
	
                        if ("string" !== typeof (name)) {
                            return false;
                        }
	
                        elements = name.split(".");
	
                        if (2 > elements.length) {
                            return false;
                        }
	
                        return {
                            name: elements[0], 
                            method: elements[1]
                        };
                    },
	
                    register: function (data) {
                        if (!data.name) {
                            console.error("Plugin name missing");
                        }
	
                        $.each($.wysiwyg, function (pluginName) {
                            if (pluginName === data.name) {
                                console.error("Plugin with name '" + data.name + "' was already registered");
                            }
                        });
	
                        $.wysiwyg[data.name] = data;
	
                        return true;
                    }
                },
	
                removeFormat: function (object) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg");
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        oWysiwyg.removeFormat();
                    });
                },
	
                save: function (object) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg");
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        oWysiwyg.saveContent();
                    });
                },
	
                selectAll: function (object) {
                    var oWysiwyg = object.data("wysiwyg"), oBody, oRange, selection;
	
                    if (!oWysiwyg) {
                        return this;
                    }
	
                    oBody = oWysiwyg.editorDoc.body;
                    if (window.getSelection) {
                        selection = oWysiwyg.getInternalSelection();
                        selection.selectAllChildren(oBody);
                    } else {
                        oRange = oBody.createTextRange();
                        oRange.moveToElementText(oBody);
                        oRange.select();
                    }
                },
	
                setContent: function (object, newContent) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg");
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        oWysiwyg.setContent(newContent);
                    });
                },
	
                triggerControl: function (object, controlName) {
                    return object.each(function () {
                        var oWysiwyg = $(this).data("wysiwyg");
	
                        if (!oWysiwyg) {
                            return this;
                        }
	
                        if (!oWysiwyg.controls[controlName]) {
                            console.error("Control '" + controlName + "' not exists");
                        }
	
                        oWysiwyg.triggerControl.apply(oWysiwyg, [controlName, oWysiwyg.controls[controlName]]);
                    });
                },
	
                support: {
                    prop: supportsProp
                },
	
                utils: {
                    extraSafeEntities: [["<", ">", "'", '"', " "], [32]],
	
                    encodeEntities: function (str) {
                        var self = this, aStr, aRet = [];
	
                        if (this.extraSafeEntities[1].length === 0) {
                            $.each(this.extraSafeEntities[0], function (i, ch) {
                                self.extraSafeEntities[1].push(ch.charCodeAt(0));
                            });
                        }
                        aStr = str.split("");
                        $.each(aStr, function (i) {
                            var iC = aStr[i].charCodeAt(0);
                            if ($.inArray(iC, self.extraSafeEntities[1]) && (iC < 65 || iC > 127 || (iC > 90 && iC < 97))) {
                                aRet.push('&#' + iC + ';');
                            } else {
                                aRet.push(aStr[i]);
                            }
                        });
	
                        return aRet.join('');
                    }
                }
            };
	
            $.fn.wysiwyg = function (method) {
                var args = arguments, plugin;
	
                if ("undefined" !== typeof $.wysiwyg[method]) {
                    // set argument object to undefined
                    args = Array.prototype.concat.call([args[0]], [this], Array.prototype.slice.call(args, 1));
                    return $.wysiwyg[method].apply($.wysiwyg, Array.prototype.slice.call(args, 1));
                } else if ("object" === typeof method || !method) {
                    Array.prototype.unshift.call(args, this);
                    return $.wysiwyg.init.apply($.wysiwyg, args);
                } else if ($.wysiwyg.plugin.exists(method)) {
                    plugin = $.wysiwyg.plugin.parseName(method);
                    args = Array.prototype.concat.call([args[0]], [this], Array.prototype.slice.call(args, 1));
                    return $.wysiwyg[plugin.name][plugin.method].apply($.wysiwyg[plugin.name], Array.prototype.slice.call(args, 1));
                } else {
                    console.error("Method '" +  method + "' does not exist on jQuery.wysiwyg.\nTry to include some extra controls or plugins");
                }
            };
		
            $.fn.getWysiwyg = function () {
                return $.data(this, "wysiwyg");
            };
        })(jQuery);
	
	
	
        /**
 * Controls: Image plugin
 *
 * Depends on jWYSIWYG
 */
        (function ($) {
            if (undefined === $.wysiwyg) {
                throw "wysiwyg.image.js depends on $.wysiwyg";
            }

            if (!$.wysiwyg.controls) {
                $.wysiwyg.controls = {};
            }

            /*
	 * Wysiwyg namespace: public properties and methods
	 */
            $.wysiwyg.controls.image = {
                init: function (Wysiwyg) {
                    var self = this, elements, dialog, formImageHtml, dialogReplacements, key, translation,
                    img = {
                        alt: "",
                        self: Wysiwyg.dom.getElement("img"), // link to element node
                        src: "http://",
                        title: ""
                    };

                    dialogReplacements = {
                        legend	: "Insert Image",
                        preview : "Preview",
                        url     : "URL",
                        title   : "Title",
                        description : "Description",
                        width   : "Width",
                        height  : "Height",
                        original : "Original W x H",
                        "float"	: "Float",
                        floatNone : "None",
                        floatLeft : "Left",
                        floatRight : "Right",
                        submit  : "Insert Image",
                        loading  : "loading",
                        reset   : "Cancel"
                    };

                    formImageHtml = '<form class="wysiwyg" title="{legend}"><fieldset>' +
                    '<label><img src="" alt="{preview}" width="100%"></label>' +
                    '<label>{url}: <input type="text" name="src" value=""></label>' +
                    '<label>{title}: <input type="text" name="imgtitle" value=""></label>' +
                    '<label>{description}: <input type="text" name="description" value=""></label>' +
                    '<label>{width} x {height}: <input type="text" name="width" value="" class="width integer"> x <input type="text" name="height" value="" class="height integer"></label><br>' +
                    '<label>{float}: <select name="float">' + 
                    '<option value="">{floatNone}</option>' +
                    '<option value="left">{floatLeft}</option>' +
                    '<option value="right">{floatRight}</option></select></label><hr>' +
                    '<button class="button" id="wysiwyg_submit">{submit}</button> ' +
                    '<button class="button" id="wysiwyg_reset">{reset}</button></fieldset></form>';

                    for (key in dialogReplacements) {
                        if ($.wysiwyg.i18n) {
                            translation = $.wysiwyg.i18n.t(dialogReplacements[key], "dialogs.image");

                            if (translation === dialogReplacements[key]) { // if not translated search in dialogs 
                                translation = $.wysiwyg.i18n.t(dialogReplacements[key], "dialogs");
                            }

                            dialogReplacements[key] = translation;
                        }

                        formImageHtml = formImageHtml.replace("{" + key + "}", dialogReplacements[key]);
                    }

                    if (img.self) {
                        img.src = img.self.src ? img.self.src : "";
                        img.alt = img.self.alt ? img.self.alt : "";
                        img.title = img.self.title ? img.self.title : "";
                        img.width = img.self.width ? img.self.width : "";
                        img.height = img.self.height ? img.self.height : "";
                        img.asp = img.width/img.width;
                    }

                    if ($.modal) {
                        elements = $(formImageHtml);
                        elements = self.makeForm(elements, img);

                        $.modal(elements, {
                            onShow: function (dialog) {
                                $("#wysiwyg_submit", dialog.data).click(function (e) {
                                    self.processInsert(dialog.container, Wysiwyg, img);

                                    $.modal.close();
                                    return false;
                                });
                                $("#wysiwyg_reset", dialog.data).click(function (e) {
                                    $.modal.close();
                                    return false;
                                });
                                $("fieldset", dialog.data).click(function (e) {
                                    e.stopPropagation();
                                });
						
                                $("select, input[type=text]", dialog).uniform();
                                $('.integer', dialog).wl_Number();
                                $('input[name="src"]', dialog).wl_URL();
						
                            },
                            maxWidth: Wysiwyg.defaults.formWidth,
                            maxHeight: Wysiwyg.defaults.formHeight,
                            overlayClose: true
                        });
                    } else if ($.fn.dialog) {
                        elements = $(formImageHtml);
                        elements = self.makeForm(elements, img);

                        dialog = elements.appendTo("body");
                        dialog.dialog({
                            modal: true,
                            resizable: false,
                            open: function (ev, ui) {
                                $("#wysiwyg_submit", dialog).click(function (e) {
                                    self.processInsert(dialog.container, Wysiwyg, img);

                                    $(dialog).dialog("close");
                                    return false;
                                });
                                $("#wysiwyg_reset", dialog).click(function (e) {
                                    $(dialog).dialog("close");
                                    return false;
                                });
                                $('fieldset', dialog).click(function (e) {
                                    e.stopPropagation();
                                });
                                $("select, input[type=text]", dialog).uniform();
                                $('.width', dialog).wl_Number({
                                    step:10,
                                    onChange:function(value){
                                        $('.height', dialog).val(Math.ceil(value/(img.asp || 1)));
                                    }								
                                });
                                $('.height', dialog).wl_Number({
                                    step:10,
                                    onChange:function(value){
                                        $('.width', dialog).val(Math.floor(value*(img.asp || 1)));
                                    }								
                                });
                                $('input[name="src"]', dialog).wl_URL();
						
                            },
                            close: function (ev, ui) {
                                dialog.dialog("destroy");
                                dialog.remove();
                            }
                        });
                    } else {
                        if ($.browser.msie) {
                            Wysiwyg.ui.focus();
                            Wysiwyg.editorDoc.execCommand("insertImage", true, null);
                        } else {
                            elements = $("<div/>")
                            .css({
                                "position": "fixed",
                                "z-index": 2000,
                                "left": "50%", 
                                "top": "50%", 
                                "background": "rgb(0, 0, 0)",
                                "margin-top": -1 * Math.round(Wysiwyg.defaults.formHeight / 2),
                                "margin-left": -1 * Math.round(Wysiwyg.defaults.formWidth / 2)
                            })
                            .html(formImageHtml);
                            elements = self.makeForm(elements, img);

                            $("#wysiwyg_submit", elements).click(function (event) {
                                self.processInsert(elements, Wysiwyg, img);

                                $(elements).remove();
                                return false;
                            });
                            $("#wysiwyg_reset", elements).click(function (event) {
                                if ($.browser.msie) {
                                    Wysiwyg.ui.returnRange();
                                }

                                $(elements).remove();
                                return false;
                            });
					
                            $("select, input[type=text]", dialog).uniform();
                            $('.integer', dialog).wl_Number();
                            $('input[name="src"]', dialog).wl_URL();
					
                            $("body").append(elements);
                            elements.click(function(e) {
                                e.stopPropagation();
                            });
                        }
                    }

                    $(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
                },

                processInsert: function (context, Wysiwyg, img) {
                    var image,
                    url = $('input[name="src"]', context).val(),
                    title = $('input[name="imgtitle"]', context).val(),
                    description = $('input[name="description"]', context).val(),
                    width = $('input[name="width"]', context).val(),
                    height = $('input[name="height"]', context).val(),
                    styleFloat = $('select[name="float"]', context).val(),
                    style = [],
                    found,
                    baseUrl;

                    if (Wysiwyg.options.controlImage.forceRelativeUrls) {
                        baseUrl = window.location.protocol + "//" + window.location.hostname;
                        if (0 === url.indexOf(baseUrl)) {
                            url = url.substr(baseUrl.length);
                        }
                    }

                    if (img.self) {
                        // to preserve all img attributes
                        $(img.self).attr("src", url)
                        .attr("title", title)
                        .attr("alt", description)
                        .css("float", styleFloat);

                        if (width.toString().match(/^[0-9]+(px|%)?$/)) {
                            $(img.self).css("width", width);
                        } else {
                            $(img.self).css("width", "");
                        }

                        if (height.toString().match(/^[0-9]+(px|%)?$/)) {
                            $(img.self).css("height", height);
                        } else {
                            $(img.self).css("height", "");
                        }
				
                        Wysiwyg.saveContent();
                    } else {
                        found = width.toString().match(/^[0-9]+(px|%)?$/);
                        if (found) {
                            if (found[1]) {
                                style.push("width: " + width + ";");
                            } else {
                                style.push("width: " + width + "px;");
                            }
                        }

                        found = height.toString().match(/^[0-9]+(px|%)?$/);
                        if (found) {
                            if (found[1]) {
                                style.push("height: " + height + ";");
                            } else {
                                style.push("height: " + height + "px;");
                            }
                        }

                        if (styleFloat.length > 0) {
                            style.push("float: " + styleFloat + ";");
                        }

                        if (style.length > 0) {
                            style = ' style="' + style.join(" ") + '"';
                        }

                        image = "<img src='" + url + "' title='" + title + "' alt='" + description + "'" + style + "/>";
                        Wysiwyg.insertHtml(image);
                    }
                },

                makeForm: function (form, img) {
                    form.find("input[name=src]").val(img.src);
                    form.find("input[name=imgtitle]").val(img.title);
                    form.find("input[name=description]").val(img.alt);
                    form.find('input[name="width"]').val(img.width);
                    form.find('input[name="height"]').val(img.height);
                    form.find('img').attr("src", img.src);
                    img.asp = img.width/img.height;
			
                    form.find("input[name=src]").bind("change", function () {
                        var image = new Image();
                        var text = $('#wysiwyg_submit',form).find('span').text();
                        form.find('img').removeAttr("src");
				
                        $('#wysiwyg_submit',form).prop('disabled',true).find('span').text('wait...');
				
                        image.onload = function(){
					
                            form.find('img').attr("src", image.src);
                            img.asp = image.width/image.height;
                            form.find('input[name="width"]').val(image.width);
                            form.find('input[name="height"]').val(image.height);
                            $('#wysiwyg_submit',form).find('span').text(text);
                            $('#wysiwyg_submit',form).prop('disabled',false);
					
                        };
                        image.src = this.value; 
                    });

                    return form;
                }
            };

            $.wysiwyg.insertImage = function (object, url, attributes) {
                return object.each(function () {
                    var Wysiwyg = $(this).data("wysiwyg"),
                    image,
                    attribute;

                    if (!Wysiwyg) {
                        return this;
                    }

                    if (!url || url.length === 0) {
                        return this;
                    }

                    if ($.browser.msie) {
                        Wysiwyg.ui.focus();
                    }

                    if (attributes) {
                        Wysiwyg.editorDoc.execCommand("insertImage", false, "#jwysiwyg#");
                        image = Wysiwyg.getElementByAttributeValue("img", "src", "#jwysiwyg#");

                        if (image) {
                            image.src = url;

                            for (attribute in attributes) {
                                if (attributes.hasOwnProperty(attribute)) {
                                    image.setAttribute(attribute, attributes[attribute]);
                                }
                            }
                        }
                    } else {
                        Wysiwyg.editorDoc.execCommand("insertImage", false, url);
                    }

                    Wysiwyg.saveContent();

                    $(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");

                    return this;
                });
            };
        })(jQuery);


        /**
 * Controls: Table plugin
 * 
 * Depends on jWYSIWYG
 */
        (function ($) {
            if (undefined === $.wysiwyg) {
                throw "wysiwyg.table.js depends on $.wysiwyg";
            }

            if (!$.wysiwyg.controls) {
                $.wysiwyg.controls = {};
            }

            var insertTable = function (colCount, rowCount, filler) {
                if (isNaN(rowCount) || isNaN(colCount) || rowCount === null || colCount === null) {
                    return;
                }

                var i, j, html = ['<table border="1" style="width: 100%;"><tbody>'];

                colCount = parseInt(colCount, 10);
                rowCount = parseInt(rowCount, 10);

                if (filler === null) {
                    filler = "&nbsp;";
                }
                filler = "<td>" + filler + "</td>";

                for (i = rowCount; i > 0; i -= 1) {
                    html.push("<tr>");
                    for (j = colCount; j > 0; j -= 1) {
                        html.push(filler);
                    }
                    html.push("</tr>");
                }
                html.push("</tbody></table>");

                return this.insertHtml(html.join(""));
            };

            /*
	 * Wysiwyg namespace: public properties and methods
	 */
            $.wysiwyg.controls.table = function (Wysiwyg) {
                var dialog, colCount, rowCount, formTableHtml,
                formTextLegend = "Insert table",
                formTextCols   = "Count of columns",
                formTextRows   = "Count of rows",
                formTextSubmit = "Insert table",
                formTextReset  = "Cancel";

                if ($.wysiwyg.i18n) {
                    formTextLegend = $.wysiwyg.i18n.t(formTextLegend, "dialogs.table");
                    formTextCols = $.wysiwyg.i18n.t(formTextCols, "dialogs.table");
                    formTextRows = $.wysiwyg.i18n.t(formTextRows, "dialogs.table");
                    formTextSubmit = $.wysiwyg.i18n.t(formTextSubmit, "dialogs.table");
                    formTextReset = $.wysiwyg.i18n.t(formTextReset, "dialogs");
                }

                formTableHtml = '<form class="wysiwyg" title="' + formTextLegend + '"><fieldset>' +
                '<label>' + formTextCols + ': <input type="text" name="colCount" value="3" class="integer" /></label><br>' +
                '<label>' + formTextRows + ': <input type="text" name="rowCount" value="3" class="integer" /></label><hr>' +
                '<button class="button" id="wysiwyg_submit">' + formTextSubmit + '</button> ' +
                '<button class="button" id="wysiwyg_reset">' + formTextReset + '</button></fieldset></form>';

                if (!Wysiwyg.insertTable) {
                    Wysiwyg.insertTable = insertTable;
                }

                if ($.fn.modal) {
                    $.modal(formTableHtml, {
                        onShow: function (dialog) {
                            $("#wysiwyg_submit", dialog.data).click(function (e) {
                                e.preventDefault();
                                rowCount = $('input[name="rowCount"]', dialog.data).val();
                                colCount = $('input[name="colCount"]', dialog.data).val();

                                Wysiwyg.insertTable(colCount, rowCount, Wysiwyg.defaults.tableFiller);
                                $.modal.close();
                            });
                            $("#wysiwyg_reset", dialog.data).click(function (e) {
                                e.preventDefault();
                                $.modal.close();
                            });
					
                            $("select, input[type=text]", dialog).uniform();
                            $('.integer', dialog).wl_Number();
					
                        },
                        maxWidth: Wysiwyg.defaults.formWidth,
                        maxHeight: Wysiwyg.defaults.formHeight,
                        overlayClose: true
                    });
                } else if ($.fn.dialog) {
                    dialog = $(formTableHtml).appendTo("body");
                    dialog.dialog({
                        modal: true,
                        resizable: false,
                        open: function (event, ui) {
                            $("#wysiwyg_submit", dialog).click(function (e) {
                                e.preventDefault();
                                rowCount = $('input[name="rowCount"]', dialog).val();
                                colCount = $('input[name="colCount"]', dialog).val();

                                Wysiwyg.insertTable(colCount, rowCount, Wysiwyg.defaults.tableFiller);
                                $(dialog).dialog("close");
                            });
                            $("#wysiwyg_reset", dialog).click(function (e) {
                                e.preventDefault();
                                $(dialog).dialog("close");
                            });
					
                            $("select, input[type=text]", dialog).uniform();
                            $('.integer', dialog).wl_Number();
					
                        },
                        close: function (event, ui) {
                            dialog.dialog("destroy");
                            dialog.remove();
                        }
                    });
                } else {
                    colCount = prompt(formTextCols, "3");
                    rowCount = prompt(formTextRows, "3");

                    Wysiwyg.insertTable(colCount, rowCount, Wysiwyg.defaults.tableFiller);
                }

                $(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
            };

            $.wysiwyg.insertTable = function (object, colCount, rowCount, filler) {
                return object.each(function () {
                    var Wysiwyg = $(this).data("wysiwyg");

                    if (!Wysiwyg.insertTable) {
                        Wysiwyg.insertTable = insertTable;
                    }

                    if (!Wysiwyg) {
                        return this;
                    }

                    Wysiwyg.insertTable(colCount, rowCount, filler);
                    $(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");

                    return this;
                });
            };
        })(jQuery);
	
        /**
 * Controls: Link plugin
 *
 * Depends on jWYSIWYG
 *
 * By: Esteban Beltran (academo) <sergies@gmail.com>
 */
        (function ($) {
            if (undefined === $.wysiwyg) {
                throw "wysiwyg.link.js depends on $.wysiwyg";
            }

            if (!$.wysiwyg.controls) {
                $.wysiwyg.controls = {};
            }

            /*
	* Wysiwyg namespace: public properties and methods
	*/
            $.wysiwyg.controls.link = {
                init: function (Wysiwyg) {
                    var self = this, elements, dialog, url, a, selection,
                    formLinkHtml, formTextLegend, formTextUrl, formTextTitle, formTextTarget,
                    formTextSubmit, formTextReset,
                    baseUrl;

                    formTextLegend  = "Insert Link";
                    formTextUrl     = "Link URL";
                    formTextTitle   = "Link Title";
                    formTextTarget  = "Link Target";
                    formTextSubmit  = "Insert Link";
                    formTextReset   = "Cancel";

                    if ($.wysiwyg.i18n) {
                        formTextLegend = $.wysiwyg.i18n.t(formTextLegend, "dialogs.link");
                        formTextUrl    = $.wysiwyg.i18n.t(formTextUrl, "dialogs.link");
                        formTextTitle  = $.wysiwyg.i18n.t(formTextTitle, "dialogs.link");
                        formTextTarget = $.wysiwyg.i18n.t(formTextTarget, "dialogs.link");
                        formTextSubmit = $.wysiwyg.i18n.t(formTextSubmit, "dialogs.link");
                        formTextReset  = $.wysiwyg.i18n.t(formTextReset, "dialogs");
                    }

                    formLinkHtml = '<form class="wysiwyg" title="' + formTextLegend + '"><fieldset>' +
                    '<label>' + formTextUrl + ': <input type="text" name="linkhref" value=""/></label>' +
                    '<label>' + formTextTitle + ': <input type="text" name="linktitle" value=""/></label>' +
                    '<label>' + formTextTarget + ': <input type="text" name="linktarget" value=""/></label><hr>' +
                    '<button class="button" id="wysiwyg_submit">' + formTextSubmit + '</button> ' +
                    '<button class="button" id="wysiwyg_reset">' + formTextReset + '</button></fieldset></form>';

                    a = {
                        self: Wysiwyg.dom.getElement("a"), // link to element node
                        href: "http://",
                        title: "",
                        target: ""
                    };

                    if (a.self) {
                        a.href = a.self.href ? a.self.href : a.href;
                        a.title = a.self.title ? a.self.title : "";
                        a.target = a.self.target ? a.self.target : "";
                    }

                    if ($.fn.dialog) {
                        elements = $(formLinkHtml);
                        elements.find("input[name=linkhref]").val(a.href);
                        elements.find("input[name=linktitle]").val(a.title);
                        elements.find("input[name=linktarget]").val(a.target);

                        if ($.browser.msie) {
                            dialog = elements.appendTo(Wysiwyg.editorDoc.body);
                        } else {
                            dialog = elements.appendTo("body");
                        }

                        dialog.dialog({
                            modal: true,
                            resizable: false,
                            open: function (ev, ui) {
                                $("#wysiwyg_submit", dialog).click(function (e) {
                                    e.preventDefault();

                                    var url = $('input[name="linkhref"]', dialog).val(),
                                    title = $('input[name="linktitle"]', dialog).val(),
                                    target = $('input[name="linktarget"]', dialog).val(),
                                    baseUrl;

                                    if (Wysiwyg.options.controlLink.forceRelativeUrls) {
                                        baseUrl = window.location.protocol + "//" + window.location.hostname;
                                        if (0 === url.indexOf(baseUrl)) {
                                            url = url.substr(baseUrl.length);
                                        }
                                    }

                                    if (a.self) {
                                        if ("string" === typeof (url)) {
                                            if (url.length > 0) {
                                                // to preserve all link attributes
                                                $(a.self).attr("href", url).attr("title", title).attr("target", target);
                                            } else {
                                                $(a.self).replaceWith(a.self.innerHTML);
                                            }
                                        }
                                    } else {
                                        if ($.browser.msie) {
                                            Wysiwyg.ui.returnRange();
                                        }

                                        //Do new link element
                                        selection = Wysiwyg.getRangeText();
                                        img = Wysiwyg.dom.getElement("img");

                                        if ((selection && selection.length > 0) || img) {
                                            if ($.browser.msie) {
                                                Wysiwyg.ui.focus();
                                            }

                                            if ("string" === typeof (url)) {
                                                if (url.length > 0) {
                                                    Wysiwyg.editorDoc.execCommand("createLink", false, url);
                                                } else {
                                                    Wysiwyg.editorDoc.execCommand("unlink", false, null);
                                                }
                                            }

                                            a.self = Wysiwyg.dom.getElement("a");

                                            $(a.self).attr("href", url).attr("title", title);

                                            /**
									 * @url https://github.com/akzhan/jwysiwyg/issues/16
									 */
                                            $(a.self).attr("target", target);
                                        } else if (Wysiwyg.options.messages.nonSelection) {
                                            $.dialog(Wysiwyg.options.messages.nonSelection);
                                        }
                                    }

                                    Wysiwyg.saveContent();

                                    $(dialog).dialog("close");
                                });
                                $("#wysiwyg_reset", dialog).click(function (e) {
                                    e.preventDefault();
                                    $(dialog).dialog("close");
                                });
					
                                $("select, input", dialog).uniform();
                                $('input[name="linkhref"]', dialog).wl_URL();
						
                            },
                            close: function (ev, ui) {
                                dialog.dialog("destroy");
                                dialog.remove();
                            }
                        });
                    } else {
                        if (a.self) {
                            url = window.prompt("URL", a.href);

                            if (Wysiwyg.options.controlLink.forceRelativeUrls) {
                                baseUrl = window.location.protocol + "//" + window.location.hostname;
                                if (0 === url.indexOf(baseUrl)) {
                                    url = url.substr(baseUrl.length);
                                }
                            }

                            if ("string" === typeof (url)) {
                                if (url.length > 0) {
                                    $(a.self).attr("href", url);
                                } else {
                                    $(a.self).replaceWith(a.self.innerHTML);
                                }
                            }
                        } else {
                            //Do new link element
                            selection = Wysiwyg.getRangeText();
                            img = Wysiwyg.dom.getElement("img");

                            if ((selection && selection.length > 0) || img) {
                                if ($.browser.msie) {
                                    Wysiwyg.ui.focus();
                                    Wysiwyg.editorDoc.execCommand("createLink", true, null);
                                } else {
                                    url = window.prompt(formTextUrl, a.href);

                                    if (Wysiwyg.options.controlLink.forceRelativeUrls) {
                                        baseUrl = window.location.protocol + "//" + window.location.hostname;
                                        if (0 === url.indexOf(baseUrl)) {
                                            url = url.substr(baseUrl.length);
                                        }
                                    }

                                    if ("string" === typeof (url)) {
                                        if (url.length > 0) {
                                            Wysiwyg.editorDoc.execCommand("createLink", false, url);
                                        } else {
                                            Wysiwyg.editorDoc.execCommand("unlink", false, null);
                                        }
                                    }
                                }
                            } else if (Wysiwyg.options.messages.nonSelection) {
                                window.alert(Wysiwyg.options.messages.nonSelection);
                            }
                        }

                        Wysiwyg.saveContent();
                    }

                    $(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
                }
            };

            $.wysiwyg.createLink = function (object, url) {
                return object.each(function () {
                    var oWysiwyg = $(this).data("wysiwyg"),
                    selection;

                    if (!oWysiwyg) {
                        return this;
                    }

                    if (!url || url.length === 0) {
                        return this;
                    }

                    selection = oWysiwyg.getRangeText();

                    if (selection && selection.length > 0) {
                        if ($.browser.msie) {
                            oWysiwyg.ui.focus();
                        }
                        oWysiwyg.editorDoc.execCommand("unlink", false, null);
                        oWysiwyg.editorDoc.execCommand("createLink", false, url);
                    } else if (oWysiwyg.options.messages.nonSelection) {
                        window.alert(oWysiwyg.options.messages.nonSelection);
                    }
                });
            };
        })(jQuery);

        /**
 * Controls: Element CSS Wrapper plugin
 *
 * Depends on jWYSIWYG
 * 
 * By Yotam Bar-On (https://github.com/tudmotu)
 */
        (function ($) {		
            if (undefined === $.wysiwyg) {
                throw "wysiwyg.cssWrap.js depends on $.wysiwyg";
            }
            /* For core enhancements #143
	$.wysiwyg.ui.addControl("cssWrap", {
		visible : false,
		groupIndex: 6,
		tooltip: "CSS Wrapper",
		exec: function () { 
				$.wysiwyg.controls.cssWrap.init(this);
			}
	}
	*/	
            if (!$.wysiwyg.controls) {
                $.wysiwyg.controls = {};
            }

            /*
	 * Wysiwyg namespace: public properties and methods
	 */
            $.wysiwyg.controls.cssWrap = {
                init: function (Wysiwyg) {
                    var self = this, formWrapHtml, key, translation,
                    dialogReplacements = {
                        legend	: "Wrap Element",
                        wrapperType : "Wrapper Type",
                        ID : "ID",
                        "class" : "Class",
                        wrap  : "Wrap",
                        unwrap: "Unwrap",
                        cancel   : "Cancel"
                    };

                    formWrapHtml = '<form class="wysiwyg" title="{legend}"><fieldset>' +
                    '<label>{wrapperType}:<select name="type"><option value="span">Span</option><option value="div">Div</option></select></label><br>' +
                    '<label>{ID}:<input name="id" type="text"></label>' + 
                    '<label>{class}:<input name="class" type="text" ></label><hr>' +
                    '<button class="cssWrap-unwrap" style="display:none;">{unwrap}</button> ' +
                    '<button class="cssWrap-submit">{wrap}</button> ' +
                    '<button class="cssWrap-cancel">{cancel}</button></fieldset></form>';

                    for (key in dialogReplacements) {
                        if ($.wysiwyg.i18n) {
                            translation = $.wysiwyg.i18n.t(dialogReplacements[key]);
                            if (translation === dialogReplacements[key]) { // if not translated search in dialogs 
                                translation = $.wysiwyg.i18n.t(dialogReplacements[key], "dialogs");
                            }
                            dialogReplacements[key] = translation;
                        }
                        formWrapHtml = formWrapHtml.replace("{" + key + "}", dialogReplacements[key]);
                    }
                    if (!$(".wysiwyg-dialog-wrapper").length) {
                        $(formWrapHtml).appendTo("body");
                        $("form.wysiwyg").dialog({
                            modal: true,
                            resizable: false,
                            open: function (ev, ui) {
                                $this = $(this);
                                var range	= Wysiwyg.getInternalRange(), common;
                                // We make sure that there is some selection:
                                if (range) {
                                    if ($.browser.msie) {
                                        Wysiwyg.ui.focus();
                                    }
                                    common	= $(range.commonAncestorContainer);
                                } else {
                                    alert("You must select some elements before you can wrap them.");
                                    $this.dialog("close");
                                    return 0;
                                }
                                var $nodeName = range.commonAncestorContainer.nodeName.toLowerCase();
                                // If the selection is already a .wysiwygCssWrapper, then we want to change it and not double-wrap it.
                                if (common.parent(".wysiwygCssWrapper").length) {
                                    alert(common.parent(".wysiwygCssWrapper").get(0).nodeName.toLowerCase());
                                    $this.find("select[name=type]").val(common.parent(".wysiwygCssWrapper").get(0).nodeName.toLowerCase());
                                    $this.find("select[name=type]").attr("disabled", "disabled");
                                    $this.find("input[name=id]").val(common.parent(".wysiwygCssWrapper").attr("id"));
                                    $this.find("input[name=class]").val(common.parent(".wysiwygCssWrapper").attr("class").replace('wysiwygCssWrapper ', ''));
                                    // Add the "unwrap" button:
                                    $("form.wysiwyg").find(".cssWrap-unwrap").show();
                                    $("form.wysiwyg").find(".cssWrap-unwrap").click(function(e) {
                                        e.preventDefault();
                                        if ($nodeName !== "body") {
                                            common.unwrap();
                                        }
                                        $this.dialog("close");
                                        return 1;
                                    });
                                }
                                // Submit button.
                                $("form.wysiwyg").find(".cssWrap-submit").click(function(e) {
                                    e.preventDefault();
                                    var $wrapper = $("form.wysiwyg").find("select[name=type]").val();
                                    var $id = $("form.wysiwyg").find("input[name=id]").val();
                                    var $class = $("form.wysiwyg").find("input[name=class]").val();
                                    if ($nodeName !== "body") {
                                        // If the selection is already a .wysiwygCssWrapper, then we want to change it and not double-wrap it.
                                        if (common.parent(".wysiwygCssWrapper").length) {
                                            common.parent(".wysiwygCssWrapper").attr("id", $class);
                                            common.parent(".wysiwygCssWrapper").attr("class", $class);
                                        } else {
                                            common.wrap('<'+$wrapper+' id="'+$id+'" class="'+"wysiwygCssWrapper "+$class+'"/>');
                                        }
                                    } else {
                                    // Currently no implemntation for if $nodeName == 'body'.
                                    }
                                    $this.dialog("close");
                                });
                                // Cancel button.
                                $("form.wysiwyg").find(".cssWrap-cancel").click(function(e) {
                                    e.preventDefault();
                                    $this.dialog("close");
                                    return 1;
                                });
                                $("form.wysiwyg").find("select, input[type=text]").uniform();
                            },
                            close: function () {
                                $(this).dialog("destroy");
                                $(this).remove();
                            }
                        });
                        Wysiwyg.saveContent();
                    }
                    $(Wysiwyg.editorDoc).trigger("editorRefresh.wysiwyg");
                    return 1;
                }
            }
        })(jQuery);

        $.fn.wl_Editor = function (method) {

            var args = arguments;
            return this.each(function () {

                var $this = $(this);


                if ($.fn.wl_Editor.methods[method]) {
                    return $.fn.wl_Editor.methods[method].apply(this, Array.prototype.slice.call(args, 1));
                } else if (typeof method === 'object' || !method) {
                    if ($this.data('wl_Editor')) {
                        var opts = $.extend({}, $this.data('wl_Editor'), method);
                    } else {
                        var opts = $.extend({}, $.fn.wl_Editor.defaults, method, $this.data());
                    }
                } else {
                    try {
                        return $this.wysiwyg(method, args[1], args[2], args[3]);
                    } catch (e) {
                        $.error('Method "' + method + '" does not exist');
                    }
                }


                if (!$this.data('wl_Editor')) {

                    $this.data('wl_Editor', {});

                    //detroying and re-made the editor crashes safari on iOS Devices so I disabled it.
                    //normally the browser don't get resized as much.
                    //wysiwyg isn't working on iPhone anyway
                    /*
			$(window).bind('resize.' + 'wl_Editor', function () {
				$this.wysiwyg('destroy').wysiwyg(opts.eOpts);
			});
			*/

                    //make an array out of the buttons or use it if it is allready an array
                    opts.buttons = opts.buttons.split('|') || opts.buttons;

                    //set initial options
                    opts.eOpts = {
                        initialContent: opts.initialContent,
                        css: opts.css
                    };

                    //set buttons visible if they are in the array
                    var controls = {};
                    $.each(opts.buttons, function (i, id) {
                        controls[id] = {
                            visible: true
                        };
                    });
			
                    //add them to the options
                    $.extend(true, opts.eOpts, {
                        controls: controls
                    }, opts.eOpts);


                    //call the jWYSIWYG plugin
                    $this.wysiwyg(opts.eOpts);

                } else {

                }

                if (opts) $.extend($this.data('wl_Editor'), opts);
            });

        };

        $.fn.wl_Editor.defaults = {
            css: 'components/com_acaweb/assets/css/whiteLabel/light/editor.css',
            buttons: 'bold|italic|underline|strikeThrough|justifyLeft|justifyCenter|justifyRight|justifyFull|highlight|indent|outdent|subscript|superscript|undo|redo|insertOrderedList|insertUnorderedList|insertHorizontalRule|createLink|insertImage|h1|h2|h3|h4|h5|h6|paragraph|rtl|ltr|cut|copy|paste|increaseFontSize|decreaseFontSize|html|code|removeFormat|insertTable',
            initialContent: ""
        };
        $.fn.wl_Editor.version = '1.0';


        $.fn.wl_Editor.methods = {
            destroy: function () {
                var $this = $(this);
                //destroy it!
                $this.wysiwyg('destroy');
                $this.removeData('wl_Editor');
            },
            set: function () {
                var $this = $(this),
                options = {};
                if (typeof arguments[0] === 'object') {
                    options = arguments[0];
                } else if (arguments[0] && arguments[1] !== undefined) {
                    options[arguments[0]] = arguments[1];
                }
                $.each(options, function (key, value) {
                    if ($.fn.wl_Editor.defaults[key] !== undefined || $.fn.wl_Editor.defaults[key] == null) {
                        $this.data('wl_Editor')[key] = value;
                    } else {
                        $.error('Key "' + key + '" is not defined');
                    }
                });

            }
        };

    });

    return jQuery;

});